home *** CD-ROM | disk | FTP | other *** search
/ Aminet 8 / Aminet 8 (1995)(GTI - Schatztruhe)[!][Oct 1995].iso / Aminet / text / hyper / wrapag.lha / WrapAG / wrapag.c < prev    next >
C/C++ Source or Header  |  1993-08-18  |  10KB  |  528 lines

  1. /* wrapag.c v1 By Bill the Hamster, godfrey2@coventry.ac.uk *
  2.  * Copyright, Bill Godfrey, UK, 1995. See file COPYING for Licence.
  3.  * Written for DICE C on the Amiga 1200.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9.  
  10. #define TRUE 1
  11. #define FALSE 0
  12. #define DEFAULTLINEWIDTH 75
  13.  
  14. int linewidth;            /* Line width, set by parameters in function main. */
  15.  
  16. struct linenode {        /* A line of text. */
  17.     char text[255];            /* The line. */
  18.     struct linenode *next;        /* List link. */
  19. };
  20.  
  21. struct paragraph {        /* A paragraph of text, made up of lines. */
  22.     struct linenode *head;        /* Head of list of lines. */
  23.     struct linenode *last;        /* Last item in list. */
  24. };
  25.  
  26. void newparagraph(struct paragraph *p)    /* Init new paragraph. */
  27. {
  28.     p->head=NULL;
  29.     p->last=NULL;
  30. }
  31.  
  32. void emptyparagraph(struct paragraph *p) /* Clear old paragraph. */ 
  33. {
  34.     struct linenode *curr;
  35.     struct linenode *link;
  36.  
  37.     curr=p->head;
  38.     while (curr != NULL) {
  39.         link=curr->next;
  40.         free(curr);
  41.         curr=link;
  42.     }
  43.     newparagraph(p);
  44. }
  45.  
  46. int addlinetop(struct paragraph *p, char *s)    /* Add line to paragraph. */
  47. {
  48.     struct linenode *nl;
  49.  
  50.     nl=malloc(sizeof(struct linenode));
  51.     
  52.     if (nl == NULL) {        /* Not enough memory? */
  53.         return(FALSE);
  54.     }
  55.     else {
  56.         strcpy(nl->text,s);    
  57.         nl->next=NULL;            /* Setup new node. */
  58.         if (p->head == NULL) {
  59.             p->head=nl;
  60.             p->last=nl;        /* Start empty list. */
  61.         }
  62.         else {
  63.             p->last->next=nl;
  64.             p->last=nl;        /* Continue existing list. */
  65.         }
  66.         
  67.         return(TRUE);
  68.     }
  69. }
  70.  
  71. void getline(FILE *inf, char *s, int maxline)    /* Get a line of text from a file. */
  72. {
  73.     char inc;    /* Charcter to be inputted. */
  74.     int charin;    /* Length of s. */
  75.  
  76.     s[0]='\0';
  77.     charin=0;
  78.  
  79.     inc=fgetc(inf);
  80.     while ((!feof(inf)) && (inc != '\n') && (charin<maxline)) {
  81.         s[charin]=inc;
  82.         charin++;
  83.         
  84.         inc=fgetc(inf);
  85.     }
  86.     s[charin]='\0';
  87. }
  88.  
  89. struct wordnode {        /* A word. */
  90.     char word[255];            /* The word. */
  91.     int alen;            /* Actual length of word. */
  92.     int vlen;            /* Virtual length. */
  93.     int ns;                /* No. of spaces. */
  94.     struct wordnode *next;        /* List link. */
  95. };
  96.  
  97. /* Paragraphs which begin with a space will have the first
  98. word as a space or tab only, with alen, vlen and ns all equal. */
  99.  
  100. struct wordlist {
  101.     struct wordnode *head;    /* Head of the word list. */
  102. };
  103.  
  104. void newwordlist(struct wordlist *wl) /* Start a new word list. */
  105. {
  106.     wl->head=NULL;
  107. }
  108.  
  109. void emptywordlist(struct wordlist *wl)    /* Empty a word list. */
  110. {
  111.     struct wordnode *curr;
  112.     struct wordnode *link;
  113.  
  114.     curr=wl->head;
  115.     while (curr != NULL) {
  116.         link=curr->next;
  117.         free(curr);
  118.         curr=link;
  119.     }
  120.     newwordlist(wl);
  121. }
  122.  
  123. void remtrail(char *s)        /* Remove all trailing whitespace. */
  124. {
  125.     int lastchar;
  126.     int c;
  127.  
  128.     lastchar=0;
  129.     c=0;
  130.  
  131.     while (s[c] != '\0') {
  132.         if ((s[c] != ' ') && (s[c] != '\t') && (s[c] != '\n') && (s[c] != '\0')) {
  133.             lastchar=c;
  134.         }
  135.         c++;
  136.     }
  137.     s[lastchar+1]='\0';
  138. }
  139.  
  140. void addaspace(char *s)
  141. {
  142.     int sl;
  143.  
  144.     sl=strlen(s);
  145.     s[sl]=' ';
  146.     s[sl+1]='\0';
  147. }
  148.  
  149. char nextchar(struct linenode *curr, int cinl)    /* Look ahead to see what the next char is. */
  150. {
  151.     char nc;
  152.  
  153.     nc=curr->text[cinl];
  154.     if (nc == '\0') {
  155.         if (curr->next != NULL) {
  156.             nc=curr->next->text[0];
  157.         }
  158.     }
  159.     return(nc);
  160. }
  161.  
  162. char loadchar(struct linenode **curr, int *cinl)
  163. {
  164.     char res;
  165.  
  166.     res=nextchar(*curr,*cinl);
  167.     if (res == '\0') {
  168.         (*curr)=NULL;
  169.         cinl=0;
  170.     }
  171.     else {
  172.         (*cinl)++;
  173.         if ((*curr)->text[*cinl] == '\0') {
  174.             if ((*curr)->next != NULL) {
  175.                 *curr=(*curr)->next;
  176.                 *cinl=0;
  177.             }
  178.         }
  179.     }
  180.     return(res);
  181. }
  182.  
  183. void setns(struct wordnode *w)
  184. {
  185.     int c;
  186.     int res;
  187.     
  188.     c=w->alen-1;    
  189.     res=0;
  190.  
  191.     while (((w->word[c] == ' ') || (w->word[c] == '\t')) && (c != 0)) {
  192.         c--;
  193.         res++;
  194.     }
  195.         
  196.     if (c == 0) {        /* If we fall out of the loop, c==0, add one to res. */
  197.         res++;
  198.     }
  199.     
  200.     w->ns=res;
  201. }
  202.  
  203. void splittowords(struct paragraph *p, struct wordlist *wl)
  204. {
  205.     struct wordnode *tempw;
  206.     struct wordnode *currw;
  207.     struct wordnode *prevw;        /* List points for wordlist. */
  208.  
  209.     struct linenode *currl;        /* Current line. */
  210.     int cinl;            /* Character in line. */
  211.  
  212.     char inc;            /* Character input. */
  213.  
  214.     int inalink;            /* Are we inside a link button text? */
  215.  
  216.     newwordlist(wl);
  217.     prevw=NULL;
  218.     currw=malloc(sizeof(struct wordnode));
  219.     wl->head=currw;
  220.  
  221.     currw->word[0]='\0';
  222.     currw->alen=0;
  223.     currw->vlen=0;
  224.     currw->ns=0;
  225.     currw->next=NULL;
  226.  
  227.     currl=p->head;
  228.     cinl=0;
  229.     inalink=FALSE;
  230.  
  231.  
  232.     inc=loadchar(&currl,&cinl);
  233.     while (inc != '\0') {
  234.         if ((inalink == TRUE) && (inc == '\"')) {
  235.             while (inc != '}') {
  236.                 currw->word[currw->alen]=inc;
  237.                 currw->alen++;
  238.                 inc=loadchar(&currl,&cinl);
  239.             }
  240.             currw->word[currw->alen]=inc;
  241.             currw->alen++;
  242.             currw->word[currw->alen]='\0';
  243.             inalink=FALSE;
  244.         }
  245.         else if (inc == '\\') {
  246.             currw->word[currw->alen]=inc;
  247.             currw->alen++;
  248.             currw->word[currw->alen]=loadchar(&currl,&cinl);
  249.             currw->alen++;
  250.             currw->word[currw->alen]='\0';
  251.  
  252.             currw->vlen++;
  253.         }
  254.         else if ((inc == '@') && (nextchar(currl,cinl) == '{')) {
  255.             inc=loadchar(&currl,&cinl);  /* And ignore it. */
  256.             inc=loadchar(&currl,&cinl);
  257.             if (inc == '\"') {
  258.                 inalink=TRUE;
  259.                 currw->word[currw->alen]='@';
  260.                 currw->alen++;
  261.                 currw->word[currw->alen]='{';
  262.                 currw->alen++;
  263.                 currw->word[currw->alen]='\"';
  264.                 currw->alen++;
  265.                 currw->word[currw->alen]='\0';
  266.             }
  267.             else {
  268.                 currw->word[currw->alen]='@';
  269.                 currw->alen++;
  270.                 currw->word[currw->alen]='{';
  271.                 currw->alen++;
  272.                 while (inc != '}') {
  273.                     currw->word[currw->alen]=inc;
  274.                     currw->alen++;
  275.                     inc=loadchar(&currl,&cinl);
  276.                 }
  277.                 currw->word[currw->alen]='}';
  278.                 currw->alen++;
  279.                 currw->word[currw->alen]='\0';
  280.             }
  281.         }
  282.         else if (((inc == ' ') || (inc == '\t')) && ((nextchar(currl,cinl) != ' ') && (nextchar(currl,cinl) != '\t'))) {
  283.             currw->word[currw->alen]=inc;
  284.             currw->alen++;
  285.             currw->word[currw->alen]='\0';
  286.  
  287.             currw->vlen++;
  288.  
  289.             setns(currw);
  290.  
  291.             if (wl->head == NULL) {    /* Empty list? */
  292.                 wl->head=currw;
  293.             }
  294.             else {            
  295.                 prevw->next=currw;
  296.                 prevw=currw;
  297.  
  298.                 tempw=malloc(sizeof(struct wordnode));
  299.                 tempw->word[0]='\0';
  300.                 tempw->alen=0;
  301.                 tempw->vlen=0;
  302.                 tempw->ns=0;
  303.                 tempw->next=NULL;
  304.  
  305.                 currw->next=tempw;
  306.                 currw=tempw;
  307.             }
  308.         }
  309.         else {
  310.             currw->word[currw->alen]=inc;
  311.             currw->alen++;
  312.             currw->word[currw->alen]='\0';
  313.             
  314.             currw->vlen++;
  315.         }
  316.         inc=loadchar(&currl,&cinl);        
  317.     }
  318.     
  319.  
  320.     if (currw->alen != 0) {
  321.         setns(currw);    
  322.         if (wl->head == NULL) {
  323.             wl->head=currw;
  324.         }
  325.         else {
  326.             prevw->next=currw;
  327.             prevw=currw;
  328.         }
  329.     }
  330. }
  331.  
  332. void testwraptext(struct wordlist *wl, int width, FILE *outf)
  333. {
  334.     struct wordnode *curr;
  335.  
  336.     printf("-=-=-=-=- New wordlist. -=-=-=-=-\n");
  337.     curr=wl->head;
  338.     while (curr != NULL) {
  339.         printf(">%s< %d %d %d\n",curr->word, curr->alen, curr->vlen, curr->ns);
  340.         curr=curr->next;
  341.     }
  342.     printf("-=-=-=-=-=- End of wordlist. -=-=-=-=-=-\n");
  343. }
  344.  
  345. void wraptext(struct wordlist *wl, int width, FILE *outf)
  346. {
  347.     struct wordnode *curr;
  348.     char work[255];        /* For modifying words. */
  349.     char line[255];        /* The current line. */
  350.     int alength;        /* Actual length of line. */
  351.     int vlength;        /* Virtual length of line. */
  352.  
  353.     alength=0;
  354.     vlength=0;
  355.     curr=wl->head;
  356.     line[0]='\0';
  357.  
  358.     while (curr != NULL) {
  359.         if (vlength + curr->vlen - curr->ns > width) {
  360.             remtrail(line);
  361.             fprintf(outf,"%s\n",line);
  362.             strcpy(line,curr->word);
  363.             alength=curr->alen;
  364.             vlength=curr->vlen;
  365.         }
  366.         else {
  367.             strcat(line,curr->word);
  368.             alength+=curr->alen;
  369.             vlength+=curr->vlen;
  370.         }
  371.         curr=curr->next;
  372.     }
  373.     fprintf(outf,"%s\n",line);
  374. }
  375.  
  376. /* Cut bit out of wrap text, inside loop.
  377.  
  378.         if (curr->vlen+charc <= width) {
  379.             fprintf(outf,"%s",curr->word);
  380.             charc += curr->vlen;
  381.         }
  382.         else if ((curr->vlen - curr->ns) + charc <= width ) {
  383.             strcpy(work,curr->word);
  384.             remtrail(work);
  385.             fprintf(outf,"%s",work);
  386.         }
  387.         else {
  388.             fprintf(outf,"\n%s",curr->word);
  389.             charc=curr->vlen;
  390.         }
  391.         curr=curr->next;
  392.  
  393. */
  394.  
  395. void testprocp(struct paragraph *p)
  396. {
  397.     struct linenode *curr;
  398.  
  399.     curr=p->head;
  400.     while (curr != NULL) {
  401.         printf(">%s<\n",curr->text);
  402.         curr=curr->next;
  403.     }
  404.  
  405. }
  406.  
  407. void procp(struct paragraph *p, FILE *outf) /* Process paragraph and output. */
  408. {
  409.     struct linenode *curr;
  410.     struct wordlist words;
  411.  
  412.     if (p->head != NULL) {
  413.         curr=p->head;
  414.         while (curr != NULL) { 
  415.             remtrail(curr->text);
  416.             if (curr->next != NULL) {
  417.                 addaspace(curr->text);
  418.             }
  419.             curr=curr->next;
  420.         }
  421.         splittowords(p,&words);
  422.         wraptext(&words,linewidth,outf);
  423.         emptywordlist(&words);
  424.     }
  425.     /*testprocp(p);*/
  426.  
  427.  
  428.  
  429. void dowrap(FILE *inf, FILE *outf)
  430. {
  431.     char s[255];
  432.     struct paragraph pgraph;
  433.  
  434.     newparagraph(&pgraph);
  435.     
  436.     getline(inf,s,254);
  437.     while (! feof(inf)) {
  438.         
  439.         if ((s[0] == '@') && (s[1] != '{')) {    /* Directive? */
  440.             procp(&pgraph,outf);
  441.             emptyparagraph(&pgraph);
  442.             fprintf(outf,"%s\n",s);
  443.         }
  444.         else if (s[0] == '\0') {        /* Blank line. */
  445.             procp(&pgraph,outf);
  446.             emptyparagraph(&pgraph);
  447.             fprintf(outf,"\n",s);
  448.         }
  449.         else if ((s[0] == ' ') || (s[0] == '\t')) {    /* Space/Tab */
  450.             procp(&pgraph,outf);
  451.             emptyparagraph(&pgraph);
  452.             addlinetop(&pgraph, s);
  453.         }
  454.         else {                    /* Normal line. */
  455.             addlinetop(&pgraph, s);
  456.         }
  457.  
  458.         getline(inf,s,254);
  459.     }
  460.     procp(&pgraph,outf);
  461. }
  462.  
  463. void syntax()
  464. {
  465.     printf("WrapAG. By Bill the Hamster.\n");
  466.     printf("  © Bill Godfrey, UK, 1995.\n\n");
  467.     printf("Syntax;\n");
  468.     printf("  WrapAG [-Wn] file.guide\n    Outputs wrapped file to screen.\n");
  469.     printf("  WrapAG [-Wn] file.guide outfile.guide\n    Outputs wrapped file to outfile.guide\n\n");
  470.     printf("\nInsert -W<number> for a specific line width, EG -W50. 74 by default.\n\n");
  471.     printf("Licensed under the GNU General Public License, Version 2.\nPlease refer to file 'COPYING' for copyright notice.\n");
  472. }
  473.  
  474. main(int argc, char **argv)
  475. {
  476.     FILE *infile;
  477.     FILE *outfile;
  478.  
  479.     int p1;
  480.  
  481.     if ((argc == 1) || (argc >= 5)) {
  482.         syntax();
  483.     }
  484.     else {
  485.         linewidth=74;        /* Set the default width. */
  486.         if ((argv[1][0] == '-') && ((argv[1][1] == 'W') || (argv[1][1] == 'w'))) {
  487.             if ((argv[1][2] < '0') || (argv[1][2] > '9')) {
  488.                 printf("Failed maths, did we?\n   N U M B E R !\n");
  489.                 syntax();
  490.                 exit(28);
  491.             }
  492.             linewidth=atoi(&argv[1][2]);
  493.             if ((linewidth < 1) || (linewidth >250)) {
  494.                 printf("A bit out of range, perhaps. Min=1, Max=250\n");
  495.                 syntax();
  496.                 exit(42);
  497.             }
  498.             p1=2;
  499.         }
  500.         else {
  501.             p1=1;
  502.         }
  503.  
  504.         infile=fopen(argv[p1],"r");
  505.         if (infile == NULL) {
  506.             printf("Error. Cannout open file, '%s'.\n",argv[1]);
  507.         }
  508.         else {
  509.             if (argc == 1+p1) {
  510.                 dowrap(infile,stdout);
  511.             }
  512.             else {
  513.                 outfile=fopen(argv[p1+1],"w");
  514.                 if (outfile == NULL) {
  515.                     printf("Error. Cannot open file. '%s'.\n",argv[2]);
  516.                 }
  517.                 else {
  518.                     dowrap(infile,outfile);
  519.                     fclose(outfile);
  520.                 }
  521.             }
  522.             fclose(infile);
  523.         }
  524.     }
  525. }
  526.  
  527.